//
//  NSObject+RunTime.m
//  Total
//
//  Created by xin on 2017/7/7.
//  Copyright © 2017年 elephants. All rights reserved.
//

#import "NSObject+RunTime.h"
#import "objc/objc-runtime.h"

@implementation NSObject (RunTime)

#pragma mark - objc_msgSend

+(id)msgSendToObj:(id)obj Selector:(SEL)selector Prarms:(NSArray*)params NeedReturn:(BOOL)needReturn{
    id returnValue = nil;
    NSInteger paramsCount = params.count;
    NSMutableArray *params_M = [NSMutableArray arrayWithArray:params];
    //
    while (params_M.count < 5) {
        [params_M addObject:@""];
    }
    params = params_M;
    //
    if (obj && selector && [obj respondsToSelector:selector] && paramsCount <= 5) {
        if (needReturn) {
            returnValue = ((id (*) (id, SEL, id, id , id, id, id)) (void *)objc_msgSend) (obj, selector, params[0], params[1], params[2], params[3], params[4]);
        }else{
            ((void (*) (id, SEL, id, id , id, id, id)) (void *)objc_msgSend)(obj, selector,  params[0], params[1], params[2], params[3], params[4]);
        }
    }
    return returnValue;
}

+(id)msgSendToClass:(Class)YSClass Selector:(SEL)selector Prarms:(NSArray*)params NeedReturn:(BOOL)needReturn{
    id returnValue = nil;
    NSInteger paramsCount = params.count;
    NSMutableArray *params_M = [NSMutableArray arrayWithArray:params];
    //
    while (params_M.count < 5) {
        [params_M addObject:@""];
    }
    params = params_M;
    //
    Method method = class_getClassMethod(YSClass, selector);
    //
    if (YSClass && selector && (int)method != 0 && paramsCount <= 5) {
        if (needReturn) {
            returnValue = ((id (*) (id, SEL, id, id , id, id, id)) (void *)objc_msgSend) (YSClass, selector, params[0], params[1], params[2], params[3], params[4]);
        }else{
            ((void (*) (id, SEL, id, id , id, id, id)) (void *)objc_msgSend)(YSClass, selector,  params[0], params[1], params[2], params[3], params[4]);
        }
    }
    return returnValue;
}

#pragma mark - NSInvocation (不限参数)

+(id)msgSendToObj_invocation:(id)obj Selector:(SEL)selector Prarms:(NSArray *)params NeedReturn:(BOOL)needReturn{
    id value = nil;
    if(obj && selector){
        if ([obj respondsToSelector:selector]) {
            NSMethodSignature * methodSignature = [[obj class] instanceMethodSignatureForSelector:selector];
            NSInvocation * invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
            [invocation setSelector:selector];
            [invocation setTarget:obj];
            [params enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                NSLog(@"idx=%ld",idx);
                [invocation setArgument:&obj atIndex:2+idx];
            }];
            [invocation invoke];
            if(needReturn){
                void *vvl = nil;//相当于OC中的id类型 void *
                [invocation getReturnValue:&vvl];
                value = (__bridge id)vvl;//桥接过来
            }
        }
    }else
    {
        
    }
    
    return value;
}

+ (id)msgSendToClass_invocation:(Class)YSClass Selector:(SEL)selector Prarms:(NSArray*)params NeedReturn:(BOOL)needReturn{
    
    id value = nil;
    Method method = class_getClassMethod(YSClass, selector);
    if ((int)method != 0) {
        NSMethodSignature * methodSignature = [YSClass instanceMethodSignatureForSelector:selector];
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
        [invocation setSelector:selector];
        [invocation setTarget:YSClass];
        [params enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            [invocation setArgument:&obj atIndex:2+idx];
        }];
        [invocation invoke];
        if(needReturn){
            void *vvl = nil;
            [invocation getReturnValue:&vvl];
            value = (__bridge id)vvl;
        }
        
    }else{
        
    }
    return value;
}

+(void)getAllIvarNameWithClass:(Class)YSClass Completed:(void (^)(NSArray *ivarNameArray))completed{
    NSMutableArray *ivarNameArray = [NSMutableArray array];
    unsigned int count = 0;
    Ivar *ivars = class_copyIvarList(YSClass, &count);
    for (int i = 0; i < count; i++){
        Ivar ivar = ivars[i];
        const char *ivarName = ivar_getName(ivar);
        NSString *ivarNameCode = [NSString stringWithUTF8String:ivarName];
        [ivarNameArray addObject:ivarNameCode];
    }
    if (completed) completed(ivarNameArray);
}

+(void)getAllPropertyNameWithClass:(Class)YSClass Completed:(void (^)(NSArray *propertyNameArray))completed
{
    NSMutableArray * propertyNameArray = [NSMutableArray array];
    unsigned int propertyCount = 0;
    objc_property_t *propertys = class_copyPropertyList(YSClass, &propertyCount);
    for (int i = 0; i < propertyCount; i++) {
        objc_property_t property = propertys[i];
        const char * propertysName = property_getName(property);
        NSString * propertysNameCode = [NSString stringWithUTF8String:propertysName];
//        NSLog(@"----%d:%@",i,propertysNameCode);
        [propertyNameArray addObject:propertysNameCode];
    }
}

@end
